home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
vol16n12.zip
/
ICONED.ZIP
/
ICON_SRC.ZIP
/
ICON.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1997-04-10
|
34KB
|
1,351 lines
unit Icon;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, Clipbrd, IconTest;
const
PixelWidth = 8;
ImageMargin = 12;
MaxUndo = 19;
crPencil = 1;
crFill = 2;
type
T16IconColors = array[0..15] of TRGBQuad;
TDrawingTools = (Capture, Pencil, Fill, Line, ClearRectangle,
FilledRectangle, ClearEllipse, FilledEllipse);
const
DefaultColors : T16IconColors =
((rgbBlue: $00; rgbGreen: $00; rgbRed: $00; rgbReserved: $00),
(rgbBlue: $00; rgbGreen: $00; rgbRed: $80; rgbReserved: $00),
(rgbBlue: $00; rgbGreen: $80; rgbRed: $00; rgbReserved: $00),
(rgbBlue: $00; rgbGreen: $80; rgbRed: $80; rgbReserved: $00),
(rgbBlue: $80; rgbGreen: $00; rgbRed: $00; rgbReserved: $00),
(rgbBlue: $80; rgbGreen: $00; rgbRed: $80; rgbReserved: $00),
(rgbBlue: $80; rgbGreen: $80; rgbRed: $00; rgbReserved: $00),
(rgbBlue: $80; rgbGreen: $80; rgbRed: $80; rgbReserved: $00),
(rgbBlue: $C0; rgbGreen: $C0; rgbRed: $C0; rgbReserved: $00),
(rgbBlue: $00; rgbGreen: $00; rgbRed: $FF; rgbReserved: $00),
(rgbBlue: $00; rgbGreen: $FF; rgbRed: $00; rgbReserved: $00),
(rgbBlue: $00; rgbGreen: $FF; rgbRed: $FF; rgbReserved: $00),
(rgbBlue: $FF; rgbGreen: $00; rgbRed: $00; rgbReserved: $00),
(rgbBlue: $FF; rgbGreen: $00; rgbRed: $FF; rgbReserved: $00),
(rgbBlue: $FF; rgbGreen: $FF; rgbRed: $00; rgbReserved: $00),
(rgbBlue: $FF; rgbGreen: $FF; rgbRed: $FF; rgbReserved: $00));
type
PIconDir = ^TIconDir;
TIconDir = record
idReserved : word;
idType : word;
idCount : word;
end;
PIconDirEntry = ^TIconDirEntry;
TIconDirEntry = record
bWidth : byte;
bHeight : byte;
bColorCount : byte;
bReserved : byte;
wPlanes : word;
wBitCount : word;
dwBytesInRes : dword;
dwImageOffset : dword;
end;
PBitMapInfoHeader = ^TBitMapInfoHeader;
TBitMapInfoHeader = record
biSize : dword;
biWidth : longint;
biHeight : longint;
biPlanes : word;
biBitCount : word;
biCompression : dword;
biSizeImage : dword;
biXPelsPerMeter : longint;
biYPelsPerMeter : longint;
biClrUsed : dword;
biClrImportant : dword;
end;
TXorMask = array[0..511] of byte;
TAndMask = array[0..127] of byte;
PIconImage = ^TIconImage;
TIconImage = record
icHeader : TBitMapInfoHeader;
icColors : T16IconColors;
icXOR : TXorMask;
icAND : TAndMask;
end;
TIconData = record
XorMask : TXorMask;
AndMask : TAndMask;
end;
PGrpIconDirEntry = ^TGrpIconDirEntry;
TGrpIconDirEntry = record
bWidth : byte;
bHeight : byte;
bColorCount : byte;
bReserved : byte;
wPlanes : word;
wBitCount : word;
dwBytesInRes : dword;
nID : word;
end;
TColorTag = 0..2;
type
TIconForm = class(TForm)
PaintBox: TPaintBox;
IconImage: TImage;
ShadowImage: TImage;
ShadowIcon: TImage;
WorkingImage: TImage;
ModifiedLabel: TLabel;
XLabel: TLabel;
YLabel: TLabel;
procedure UpdateCursor;
procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
procedure SetupWindow;
procedure SetupUndoBuff;
function LookupColorIndex(ARGBQuadColor : TRGBQuad) : integer;
function QuadColorToColor(ARGBQuadColor : TRGBQuad) : TColor;
function RGBColorToQuadColor(ARGBColor : TColor) : TRGBQuad;
function GetUndoColor(x, y : integer;
var MaskBit : boolean) : TColor;
procedure UndoToIcon;
procedure WorkingToIcon;
procedure WorkingToUndo;
procedure UndoToCapturedBuffer;
procedure CapturedBufferToWorking;
procedure NextUndo;
procedure PreviousUndo;
procedure FormPaint(Sender: TObject);
procedure SaveIcon(Sender: TObject);
procedure TestIcon(Sender: TObject);
procedure CopyCaptured;
procedure CutCaptured;
procedure FormCreate(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormDestroy(Sender: TObject);
procedure PaintBoxMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBoxDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure PaintBoxEndDrag(Sender, Target: TObject; X, Y: Integer);
procedure PaintBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure CaptureBegin;
procedure CapturingDraw;
procedure CapturedDraw;
procedure Paste;
procedure SelectAll;
procedure PencilDraw;
procedure FillDraw;
procedure LineDraw(ACanvas : TCanvas);
procedure GetRectCorners(var SX, SY, EX, EY : integer);
procedure RectangleDraw(ACanvas : TCanvas);
procedure ClearRectangleDraw(ACanvas : TCanvas);
procedure FilledRectangleDraw(ACanvas : TCanvas);
procedure EllipseDraw(ACanvas : TCanvas);
procedure ClearEllipseDraw(ACanvas : TCanvas);
procedure FilledEllipseDraw(ACanvas : TCanvas);
private
{ Private declarations }
UndoIndex : integer;
UndoBuffer : array[0..MaxUndo] of TIconData;
StartPos, EndPos, LastPos : TPoint;
DrawingColor, PixelColor, WorkingColor : TColor;
DrawingColorIndex : integer;
ColorTag : TColorTag;
Modified : boolean;
Drawn : boolean;
CapturedOrgStart, CapturedOrgEnd : TPoint;
CapturedDestStart, CapturedDestEnd : TPoint;
CapturedDiff : TPoint;
CapturedBuffer : TIconData;
Pasted : boolean;
public
{ Public declarations }
IconTool : TDrawingTools;
IconFileName : string;
IconSize : integer;
ImageOffset : pchar;
IconColors : array[0..15] of TRGBQuad;
F: file;
IconFileSize : longint;
IconBuffer : pchar;
NewIcon : boolean;
UndoCount : integer;
Captured, CapturedDragging : boolean;
end;
var
IconForm: TIconForm;
implementation
{$R *.DFM}
{$R CURSORS.RES}
uses Main;
procedure TIconForm.UpdateCursor;
begin
case IconTool of
Pencil :
begin
PaintBox.Cursor:= crPencil;
PaintBox.DragCursor:= crPencil;
end;
Fill :
begin
PaintBox.Cursor:= crFill;
PaintBox.DragCursor:= crFill;
end;
Capture, Line..FilledEllipse :
begin
PaintBox.Cursor:= crCross;
PaintBox.DragCursor:= crCross;
end;
end;
end;
procedure TIconForm.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
with Msg do
if (Message = WM_RBUTTONUP) and
(PaintBox.Dragging) then
Message:= WM_LBUTTONUP;
end;
procedure TIconForm.SetupWindow;
begin
with PaintBox do
begin
Top:= 1;
Width:= IconSize * PixelWidth + 1;
Height:= IconSize * PixelWidth + 1;
ShadowImage.Width:= Width;
ShadowImage.Height:= Height;
end;
with IconImage do
begin
Width:= IconSize;
Height:= IconSize;
Left:= PaintBox.Left + PaintBox.Width + ImageMargin;
Top:= (PaintBox.Height - Height) div 2;
XLabel.Top:= Top + Height + XLabel.Height;
XLabel.Left:= Left + 4;
YLabel.Top:= XLabel.Top + XLabel.Height;
YLabel.Left:= Left + 4;
ModifiedLabel.Top:= YLabel.Top + YLabel.Height * 2;
ModifiedLabel.Left:= Left + (Width - ModifiedLabel.Width) div 2;
end;
Width:= IconImage.Left + IconImage.Width +
GetSystemMetrics(SM_CXSIZEFRAME) +
ImageMargin;
Height:= PaintBox.Height +
GetSystemMetrics(SM_CYSIZEFRAME) * 2 +
GetSystemMetrics(SM_CYCAPTION);
end;
procedure TIconForm.SetupUndoBuff;
var
PIndex : pchar;
begin
PIndex:= ImageOffset;
Move(PIconImage(PIndex).icXOR,
UndoBuffer[UndoIndex].XorMask,
sizeof(TXorMask));
Move(PIconImage(PIndex).icAND,
UndoBuffer[UndoIndex].AndMask,
sizeof(TAndMask));
UndoToIcon;
end;
function TIconForm.LookupColorIndex(ARGBQuadColor : TRGBQuad) : integer;
begin
for Result:= 0 to 15 do
if dword(IconColors[Result]) =
dword(ARGBQuadColor) then
break;
end;
function TIconForm.QuadColorToColor(ARGBQuadColor : TRGBQuad) : TColor;
begin
Result:= RGB(ARGBQuadColor.rgbRed,
ARGBQuadColor.rgbGreen,
ARGBQuadColor.rgbBlue);
end;
function TIconForm.RGBColorToQuadColor(ARGBColor : TColor) : TRGBQuad;
begin
Result.rgbRed:= (ARGBColor and $000000FF);
Result.rgbGreen:= (ARGBColor and $0000FF00) shr (4 * 2);
Result.rgbBlue:= (ARGBColor and $00FF0000) shr (4 * 4);
Result.rgbReserved:= 0;
end;
function TIconForm.GetUndoColor(x, y : integer;
var MaskBit : boolean) : TColor;
var
XorIndex, AndIndex : integer;
ColorNibble : byte;
begin
XorIndex:= x div 2 + (31 - y) * 16;
AndIndex:= (31 - y) * 4 + (x shr 3);
if odd(x) then
ColorNibble:=
UndoBuffer[UndoIndex].XorMask[XorIndex] and
$0F
else
ColorNibble:=
UndoBuffer[UndoIndex].XorMask[XorIndex] and
$F0 shr 4;
MaskBit:= (UndoBuffer[UndoIndex].AndMask[AndIndex]) and
(1 shl (7 - (x mod 8))) <> 0;
if MaskBit then
if ColorNibble = 0 then
Result:= MainForm.TransparentPanel.Color
else
Result:= MainForm.ReversePanel.Color
else
Result:= RGB(IconColors[ColorNibble].rgbRed,
IconColors[ColorNibble].rgbGreen,
IconColors[ColorNibble].rgbBlue);
end;
procedure TIconForm.UndoToIcon;
var
x, y : integer;
MaskBit : boolean;
begin
for y:= 0 to IconSize - 1 do
for x:= 0 to IconSize - 1 do
ShadowIcon.Canvas.Pixels[x, y]:=
GetUndoColor(x, y, MaskBit);
with ShadowIcon do
IconImage.Canvas.CopyRect(ClientRect,
Canvas,
ClientRect);
end;
procedure TIconForm.WorkingToIcon;
begin
with IconImage.Canvas do
CopyRect(Rect(CapturedDestStart.X,
CapturedDestStart.Y,
CapturedDestEnd.X + 1,
CapturedDestEnd.Y + 1),
WorkingImage.Canvas,
Rect(CapturedOrgStart.X,
CapturedOrgStart.Y,
CapturedOrgEnd.X + 1,
CapturedOrgEnd.Y + 1));
end;
procedure TIconForm.WorkingToUndo;
var
NewColorIndex : integer;
XorIndex, AndIndex : integer;
x, y : integer;
begin
NewColorIndex:= 0;
case ColorTag of
0 : NewColorIndex:= DrawingColorIndex;
1 : NewColorIndex:= 0;
2 : NewColorIndex:= $F;
end;
for x:= 0 to IconSize - 1 do
for y:= 0 to IconSize - 1 do
if WorkingImage.Canvas.Pixels[x, y] =
DrawingColor then
begin
XorIndex:= x div 2 + (31 - y) * 16;
AndIndex:= (31 - y) * 4 + (x shr 3);
with UndoBuffer[UndoIndex] do
begin
if odd(x) then
XorMask[XorIndex]:= XorMask[XorIndex] and
$F0 or
NewColorIndex
else
XorMask[XorIndex]:= XorMask[XorIndex] and
$0F or
NewColorIndex shl 4;
if ColorTag = 0 then
AndMask[AndIndex]:= AndMask[AndIndex] and
not (1 shl (7 - (x mod 8)))
else
AndMask[AndIndex]:= AndMask[AndIndex] or
(1 shl (7 - (x mod 8)))
end;
end;
end;
procedure TIconForm.UndoToCapturedBuffer;
begin
Move(UndoBuffer[UndoIndex].XorMask,
CapturedBuffer.XorMask,
sizeof(TXorMask));
Move(UndoBuffer[UndoIndex].AndMask,
CapturedBuffer.AndMask,
sizeof(TAndMask));
end;
procedure TIconForm.CapturedBufferToWorking;
var
x, y : integer;
XorIndex, AndIndex : integer;
ColorNibble : byte;
AColor : TColor;
begin
for y:= CapturedOrgStart.Y to CapturedOrgEnd.Y do
for x:= CapturedOrgStart.X to CapturedOrgEnd.X do
begin
XorIndex:= x div 2 + (31 - y) * 16;
AndIndex:= (31 - y) * 4 + (x shr 3);
if odd(x) then
ColorNibble:=
CapturedBuffer.XorMask[XorIndex] and
$0F
else
ColorNibble:=
CapturedBuffer.XorMask[XorIndex] and
$F0 shr 4;
if (CapturedBuffer.AndMask[AndIndex]) and
(1 shl (7 - (x mod 8))) <> 0 then
if ColorNibble = 0 then
AColor:= MainForm.TransparentPanel.Color
else
AColor:= MainForm.ReversePanel.Color
else
AColor:= RGB(IconColors[ColorNibble].rgbRed,
IconColors[ColorNibble].rgbGreen,
IconColors[ColorNibble].rgbBlue);
WorkingImage.Canvas.Pixels[x + CapturedDiff.X,
y + CapturedDiff.Y]:=
AColor;
end;
end;
procedure TIconForm.NextUndo;
var
LastIndex : integer;
begin
LastIndex:= UndoIndex;
if UndoCount < MaxUndo then
inc(UndoCount);
if UndoIndex < MaxUndo then
inc(UndoIndex)
else
UndoIndex:= 0;
Move(UndoBuffer[LastIndex].XorMask,
UndoBuffer[UndoIndex].XorMask,
sizeof(TXorMask));
Move(UndoBuffer[LastIndex].AndMask,
UndoBuffer[UndoIndex].AndMask,
sizeof(TAndMask));
end;
procedure TIconForm.PreviousUndo;
begin
if UndoCount = 0 then exit;
CapturedDraw;
dec(UndoCount);
if UndoIndex > 0 then
dec(UndoIndex)
else
UndoIndex:= MaxUndo;
UndoToIcon;
FormPaint(Self);
end;
procedure TIconForm.FormPaint(Sender: TObject);
var
i : integer;
begin
StretchBlt(ShadowImage.Canvas.Handle,
0,
0,
ShadowImage.Width,
ShadowImage.Height,
IconImage.Canvas.Handle,
0,
0,
IconImage.Width,
IconImage.Height,
SrcCopy);
if MainForm.ShowPixels.Checked then
with ShadowImage.Canvas do
begin
Pen.Color:= clBlack;
Pen.Style:= psSolid;
for i:= 0 to IconSize do
begin
MoveTo(i * PixelWidth, 0);
LineTo(i * PixelWidth, IconSize * PixelWidth + 1);
MoveTo(0, i * PixelWidth);
LineTo(IconSize * PixelWidth + 1, i * PixelWidth);
end;
end;
if Captured then
with ShadowImage.Canvas do
begin
Pen.Color:= clWhite;
Pen.Style:= psDot;
Brush.Style:= bsClear;
Rectangle(CapturedDestStart.X * PixelWidth + 1,
CapturedDestStart.Y * PixelWidth + 1,
(CapturedDestEnd.X + 1) * PixelWidth,
(CapturedDestEnd.Y + 1) * PixelWidth);
end;
BitBlt(PaintBox.Canvas.Handle,
0,
0,
PaintBox.Width,
PaintBox.Height,
ShadowImage.Canvas.Handle,
0,
0,
SrcCopy);
IconImage.Repaint;
end;
procedure TIconForm.SaveIcon(Sender: TObject);
var
PIndex : pchar;
NumWritten : longint;
begin
CapturedDraw;
PIndex:= ImageOffset;
Move(UndoBuffer[UndoIndex].XorMask,
PIconImage(PIndex).icXOR,
sizeof(TXorMask));
Move(UndoBuffer[UndoIndex].AndMask,
PIconImage(PIndex).icAND,
sizeof(TAndMask));
{$I-}
AssignFile(F, IconFileName);
FileMode:= 1;
Rewrite(F, 1);
{$I+}
if IOResult <> 0 then exit;
BlockWrite(F, IconBuffer^, IconFileSize, NumWritten);
CloseFile(F);
Modified:= false;
ModifiedLabel.Visible:= false;
end;
procedure TIconForm.TestIcon(Sender : TObject);
var
TempIconName : string;
TempModified : boolean;
begin
with TIconTestForm.Create(Application) do
try
ColorGrid1.ForegroundIndex:= MainForm.TestColorIndex;
Caption:= ExtractFileName(IconFileName) + ' Test';
TempIconName:= IconFileName;
TempModified:= Modified;
IconFileName:= MainForm.TempIconFile;
SaveIcon(Sender);
TestImage.Picture.LoadFromFile(IconFileName);
ShowModal;
MainForm.TestColorIndex:= ColorGrid1.ForegroundIndex;
DeleteFile(IconFileName);
IconFileName:= TempIconName;
Modified:= TempModified;
finally
Free;
end;
end;
procedure TIconForm.CopyCaptured;
var
hClipGlobal : THandle;
PClipIcon, PIndex : pchar;
ClipSize, CapturedLine : integer;
CapturedWidth, CapturedHeight : integer;
CapturedX, CapturedY, LineX : integer;
y, i : integer;
TempLine : array[0..15] of byte;
begin
if (not CapturedDragging) and
(not Pasted) then
UndoToCapturedBuffer;
ClipSize:= sizeof(TIconImage) - sizeof(TAndMask);
hClipGlobal:= GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE,
ClipSize);
if hClipGlobal = 0 then
exit;
PClipIcon:= GlobalLock(hClipGlobal);
if not OpenClipboard(Handle) then
begin
GlobalUnlock(hClipGlobal);
exit;
end;
CapturedWidth:= CapturedOrgEnd.X - CapturedOrgStart.X + 1;
CapturedHeight:= CapturedOrgEnd.Y - CapturedOrgStart.Y + 1;
CapturedLine:= (CapturedWidth * 4 + 31) div 32 * 4;
PIndex:= @PClipIcon[0];
FillChar(PIconImage(PIndex).icHeader,
sizeof(PIconImage(PIndex).icHeader),
0);
PIconImage(PIndex).icHeader.biSize:= sizeof(TBitMapInfoHeader);
PIconImage(PIndex).icHeader.biWidth:= CapturedWidth;
PIconImage(PIndex).icHeader.biHeight:= CapturedHeight;
PIconImage(PIndex).icHeader.biPlanes:= 1;
PIconImage(PIndex).icHeader.biBitCount:= 4;
PIconImage(PIndex).icHeader.bisizeimage:=
CapturedLine * CapturedHeight;
Move(DefaultColors,
PIconImage(PIndex).icColors,
16 * sizeof(TRGBQuad));
PIndex:= @PClipIcon[sizeof(TBitmapInfoHeader) +
sizeof(T16IconColors)];
CapturedX:= CapturedOrgStart.X div 2;
CapturedY:= 32 - CapturedOrgStart.Y - CapturedHeight;
for y:= 0 to CapturedHeight - 1 do
begin
LineX:= CapturedX + (CapturedY + y) * 16;
Move(CapturedBuffer.XorMask[LineX], TempLine, CapturedLine);
if odd(CapturedOrgStart.X) then
begin
for i:= 0 to CapturedWidth - 1 do
TempLine[i]:= ((TempLine[i] and $0F) shl 4) or
((TempLine[i + 1] and $F0) shr 4);
end;
Move(TempLine, PIndex[y * CapturedLine], CapturedLine);
end;
EmptyClipboard;
SetClipboardData(CF_DIB, hClipGlobal);
CloseClipboard;
GlobalUnlock(hClipGlobal);
end;
procedure TIconForm.CutCaptured;
var
x, y : integer;
XorIndex, AndIndex : integer;
begin
CopyCaptured;
NextUndo;
for y:= CapturedDestStart.Y to CapturedDestEnd.Y do
for x:= CapturedDestStart.X to CapturedDestEnd.X do
begin
XorIndex:= x div 2 + (31 - y) * 16;
AndIndex:= (31 - y) * 4 + (x shr 3);
with UndoBuffer[UndoIndex] do
begin
if odd(x) then
XorMask[XorIndex]:= XorMask[XorIndex] and
$F0
else
XorMask[XorIndex]:= XorMask[XorIndex] and
$0F;
AndMask[AndIndex]:= AndMask[AndIndex] or
(1 shl (7 - (x mod 8)));
end;
end;
UndoToIcon;
Captured:= false;
CapturedDragging:= false;
Pasted:= false;
UpdateCursor;
FormPaint(Self);
end;
procedure TIconForm.FormCreate(Sender: TObject);
begin
Application.OnMessage:= AppMessage;
Screen.Cursors[crSize]:= LoadCursor(hInstance, 'GRABHAND');
Screen.Cursors[crPencil]:= LoadCursor(hInstance, 'PENCIL');
Screen.Cursors[crFill]:= LoadCursor(hInstance, 'FILL');
IconTool:= Pencil;
UpdateCursor;
end;
procedure TIconForm.FormActivate(Sender: TObject);
begin
with MainForm do
begin
DrawingTool:= IconTool;
UpdateTool;
end;
end;
procedure TIconForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
end;
procedure TIconForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
i : integer;
begin
if Modified then
begin
BringToFront;
i:= MessageDlg('Save changes to ' + IconFileName,
mtConfirmation, [mbYes, mbNo, mbCancel], 0);
if i = mrYes then
SaveIcon(Sender);
if i = mrCancel then
CanClose:= false;
end;
end;
procedure TIconForm.FormDestroy(Sender: TObject);
begin
if assigned(IconBuffer) then
FreeMem(IconBuffer, IconFileSize);
end;
procedure TIconForm.PaintBoxMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
AX, AY : integer;
RGBQuadDrawingColor, RGBQuadPixelColor : TRGBQuad;
WorkingColorIndex : integer;
FillColorIndex : integer;
FillColor : TColor;
PixelMaskBit, ColorMaskBit : boolean;
begin
case Button of
mbLeft :
begin
DrawingColor:= MainForm.LeftButtonPanel.Color;
ColorTag:= MainForm.LeftButtonPanel.Tag;
end;
mbRight :
begin
DrawingColor:= MainForm.RightButtonPanel.Color;
ColorTag:= MainForm.RightButtonPanel.Tag;
end;
mbMiddle : exit;
end;
AX:= X;
AY:= Y;
StartPos.X:= (AX - 1) div PixelWidth;
StartPos.Y:= (AY - 1) div PixelWidth;
EndPos.X:= StartPos.X;
EndPos.Y:= StartPos.Y;
LastPos.X:= StartPos.X;
LastPos.Y:= StartPos.Y;
if IconTool <> Capture then
begin
RGBQuadDrawingColor:= RGBColorToQuadColor(
ColorToRGB(DrawingColor));
DrawingColorIndex:= LookupColorIndex(RGBQuadDrawingColor);
PixelColor:= GetUndoColor(StartPos.X, StartPos.Y, PixelMaskBit);
RGBQuadPixelColor:= RGBColorToQuadColor(
ColorToRGB(PixelColor));
for FillColorIndex:= 0 to 15 do
if (dword(IconColors[FillColorIndex]) <>
dword(RGBQuadDrawingColor)) and
(dword(IconColors[FillColorIndex]) <>
dword(RGBQuadPixelColor)) then
break;
FillColor:= QuadColorToColor(IconColors[FillColorIndex]);
with WorkingImage.Canvas do
begin
Brush.Color:= FillColor;
FillRect(ClientRect);
end;
if IconTool = Fill then
begin
for WorkingColorIndex:= 0 to 15 do
if (dword(IconColors[WorkingColorIndex]) <>
dword(RGBQuadDrawingColor)) and
(dword(IconColors[WorkingColorIndex]) <>
dword(RGBQuadPixelColor)) and
(FillColorIndex <>
WorkingColorIndex) then
break;
WorkingColor:= QuadColorToColor(IconColors[WorkingColorIndex]);
for AY:= 0 to IconSize - 1 do
for AX:= 0 to IconSize - 1 do
if (GetUndoColor(AX, AY, ColorMaskBit) = PixelColor) and
(ColorMaskBit = PixelMaskBit) then
WorkingImage.Canvas.Pixels[AX, AY]:= WorkingColor;
end;
end;
case IconTool of
Capture : CaptureBegin;
Pencil : PencilDraw;
Fill : FillDraw;
end;
if IconTool <> Fill then
PaintBox.BeginDrag(false);
FormPaint(Sender);
end;
procedure TIconForm.PaintBoxDragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
var
AX, AY : integer;
begin
AX:= (X - 1) div PixelWidth;
AY:= (Y - 1) div PixelWidth;
XLabel.Caption:= 'X: ' + IntToStr(AX);
YLabel.Caption:= 'Y: ' + IntToStr(AY);
EndPos.X:= AX;
EndPos.Y:= AY;
if (EndPos.X = LastPos.X) and
(EndPos.Y = LastPos.Y) then
exit;
if (IconTool <> Pencil) and
(IconTool <> Capture) then
UndoToIcon;
with IconImage do
case IconTool of
Capture : CapturingDraw;
Pencil : PencilDraw;
Fill : exit;
ClearRectangle : ClearRectangleDraw(Canvas);
FilledRectangle : FilledRectangleDraw(Canvas);
ClearEllipse : ClearEllipseDraw(Canvas);
FilledEllipse : FilledEllipseDraw(Canvas);
Line : LineDraw(Canvas);
end;
if IconTool <> Capture then
begin
Modified:= true;
ModifiedLabel.Visible:= true;
Drawn:= true;
end;
LastPos.X:= EndPos.X;
LastPos.Y:= EndPos.Y;
FormPaint(Sender);
end;
procedure TIconForm.PaintBoxEndDrag(Sender, Target: TObject;
X, Y: Integer);
begin
if not Drawn then exit;
Drawn:= false;
with WorkingImage do
case IconTool of
Capture : exit;
Pencil : ;
Fill : exit;
ClearRectangle : ClearRectangleDraw(Canvas);
FilledRectangle : FilledRectangleDraw(Canvas);
ClearEllipse : ClearEllipseDraw(Canvas);
FilledEllipse : FilledEllipseDraw(Canvas);
Line : LineDraw(Canvas);
end;
NextUndo;
WorkingToUndo;
UndoToIcon;
FormPaint(Sender);
end;
procedure TIconForm.PaintBoxMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
var
AX, AY : integer;
begin
AX:= (X - 1) div PixelWidth;
AY:= (Y - 1) div PixelWidth;
XLabel.Caption:= 'X: ' + IntToStr(AX);
YLabel.Caption:= 'Y: ' + IntToStr(AY);
if (Captured) and
(AX >= CapturedDestStart.X) and
(AX <= CapturedDestEnd.X) and
(AY >= CapturedDestStart.Y) and
(AY <= CapturedDestEnd.Y) then
PaintBox.Cursor:= crSize
else
UpdateCursor;
end;
procedure TIconForm.CaptureBegin;
begin
if not Captured then exit;
if (StartPos.X >= CapturedDestStart.X) and
(EndPos.X <= CapturedDestEnd.X) and
(StartPos.Y >= CapturedDestStart.Y) and
(EndPos.Y <= CapturedDestEnd.Y) then
begin
if (not CapturedDragging) and
(not Pasted) then
begin
UndoToCapturedBuffer;
CapturedBufferToWorking;
end;
CapturedDragging:= true;
PaintBox.DragCursor:= crSize;
end
else
CapturedDraw;
end;
procedure TIconForm.CapturingDraw;
begin
if CapturedDragging then
begin
if (StartPos.X = EndPos.X) and
(StartPos.Y = EndPos.Y) then
exit;
CapturedDiff.X:= CapturedDiff.X + EndPos.X - LastPos.X;
CapturedDiff.Y:= CapturedDiff.Y + EndPos.Y - LastPos.Y;
CapturedDestStart.X:= CapturedOrgStart.X + CapturedDiff.X;
CapturedDestStart.Y:= CapturedOrgStart.Y + CapturedDiff.Y;
CapturedDestEnd.X:= CapturedOrgEnd.X + CapturedDiff.X;
CapturedDestEnd.Y:= CapturedOrgEnd.Y + CapturedDiff.Y;
UndoToIcon;
WorkingToIcon;
end
else
begin
if (StartPos.X = EndPos.X) or
(StartPos.Y = EndPos.Y) then
begin
Captured:= false;
exit;
end;
if StartPos.X < EndPos.X then
begin
CapturedOrgStart.X:= StartPos.X;
CapturedOrgEnd.X:= EndPos.X;
end
else
begin
CapturedOrgStart.X:= EndPos.X;
CapturedOrgEnd.X:= StartPos.X;
end;
if StartPos.Y < EndPos.Y then
begin
CapturedOrgStart.Y:= StartPos.Y;
CapturedOrgEnd.Y:= EndPos.Y;
end
else
begin
CapturedOrgStart.Y:= EndPos.Y;
CapturedOrgEnd.Y:= StartPos.Y;
end;
CapturedDestStart.X:= CapturedOrgStart.X;
CapturedDestStart.Y:= CapturedOrgStart.Y;
CapturedDestEnd.X:= CapturedOrgEnd.X;
CapturedDestEnd.Y:= CapturedOrgEnd.Y;
CapturedDiff.X:= 0;
CapturedDiff.Y:= 0;
Captured:= true;
end;
end;
procedure TIconForm.CapturedDraw;
var
x, y : integer;
Dest : TPoint;
XorIndex, AndIndex : integer;
ColorNibble, AndBit : integer;
begin
if not Captured then exit;
UpdateCursor;
Captured:= false;
CapturedDragging:= false;
FormPaint(Self);
if (CapturedDiff.X = 0) and
(CapturedDiff.Y = 0) and
(not Pasted) then
exit;
Pasted:= false;
NextUndo;
Modified:= true;
ModifiedLabel.Visible:= true;
for y:= CapturedOrgStart.Y to CapturedOrgEnd.Y do
for x:= CapturedOrgStart.X to CapturedOrgEnd.X do
begin
Dest.X:= x + CapturedDiff.X;
Dest.Y:= y + CapturedDiff.Y;
if (Dest.X < 0) or
(Dest.X > IconSize - 1) or
(Dest.Y < 0) or
(Dest.Y > IconSize - 1) then
continue;
XorIndex:= x div 2 + (31 - y) * 16;
AndIndex:= (31 - y) * 4 + (x shr 3);
if odd(x) then
ColorNibble:=
CapturedBuffer.XorMask[XorIndex] and
$0F
else
ColorNibble:=
CapturedBuffer.XorMask[XorIndex] and
$F0 shr 4;
AndBit:= CapturedBuffer.AndMask[AndIndex] and
(1 shl (7 - (x mod 8)));
XorIndex:= Dest.X div 2 + (31 - Dest.Y) * 16;
AndIndex:= (31 - Dest.Y) * 4 + (Dest.X shr 3);
with UndoBuffer[UndoIndex] do
begin
if odd(Dest.X) then
XorMask[XorIndex]:= XorMask[XorIndex] and
$F0 or
ColorNibble
else
XorMask[XorIndex]:= XorMask[XorIndex] and
$0F or
ColorNibble shl 4;
if AndBit = 0 then
AndMask[AndIndex]:= AndMask[AndIndex] and
not (1 shl (7 - (Dest.X mod 8)))
else
AndMask[AndIndex]:= AndMask[AndIndex] or
(1 shl (7 - (Dest.X mod 8)))
end;
end;
FormPaint(Self);
end;
procedure TIconForm.Paste;
var
hClipGlobal : THandle;
PClipIcon, PIndex : pchar;
ClipWidth, ClipHeight : integer;
ClipLine : integer;
y : integer;
begin
CapturedDraw;
if not Clipboard.HasFormat(CF_DIB) then exit;
if not OpenClipboard(Handle) then exit;
hClipGlobal:= GetClipboardData(CF_DIB);
PClipIcon:= GlobalLock(hClipGlobal);
if (hClipGlobal = 0) or
(PClipIcon = nil) then
begin
CloseClipboard;
ShowMessage('Paste failed');
exit;
end;
PIndex:= @PClipIcon[0];
ClipWidth:= PBitMapInfoHeader(PIndex).biWidth;
ClipHeight:= PBitMapInfoHeader(PIndex).biHeight;
if (ClipWidth = 0) or
(ClipWidth > 32) or
(ClipHeight <= 0) or
(ClipHeight > 32) or
(PBitMapInfoHeader(PIndex).biPlanes <> 1) or
(PBitMapInfoHeader(PIndex).biBitCount <> 4) or
(PBitMapInfoHeader(PIndex).biCompression <> 0) then
begin
CloseClipboard;
ShowMessage('Bitmap format or size not supported');
exit;
end;
PIndex:= @PClipIcon[PBitMapInfoHeader(PClipIcon).biSize +
sizeof(T16IconColors)];
ClipLine:= (ClipWidth * 4 + 31) div 32 * 4;
for y:= 0 to ClipHeight - 1 do
Move(PIndex[y * ClipLine],
CapturedBuffer.XorMask[(32 - ClipHeight + y) * 16],
ClipLine);
FillChar(CapturedBuffer.AndMask,
sizeof(TAndMask),
0);
CapturedOrgStart.X:= 0;
CapturedOrgStart.Y:= 0;
CapturedOrgEnd.X:= ClipWidth - 1;
CapturedOrgEnd.Y:= ClipHeight - 1;
CapturedDestStart.X:= CapturedOrgStart.X;
CapturedDestStart.Y:= CapturedOrgStart.Y;
CapturedDestEnd.X:= CapturedOrgEnd.X;
CapturedDestEnd.Y:= CapturedOrgEnd.Y;
CapturedDiff.X:= 0;
CapturedDiff.Y:= 0;
CapturedBufferToWorking;
WorkingToIcon;
Captured:= true;
Pasted:= true;
IconTool:= Capture;
with MainForm do
begin
DrawingTool:= IconTool;
UpdateTool;
end;
GlobalUnlock(hClipGlobal);
CloseClipboard;
Modified:= true;
ModifiedLabel.Visible:= true;
FormPaint(Self);
end;
procedure TIconForm.SelectAll;
begin
CapturedDraw;
CapturedOrgStart.X:= 0;
CapturedOrgStart.Y:= 0;
CapturedOrgEnd.X:= 31;
CapturedOrgEnd.Y:= 31;
CapturedDestStart.X:= 0;
CapturedDestStart.Y:= 0;
CapturedDestEnd.X:= 31;
CapturedDestEnd.Y:= 31;
CapturedDiff.X:= 0;
CapturedDiff.Y:= 0;
Captured:= true;
IconTool:= Capture;
with MainForm do
begin
DrawingTool:= IconTool;
UpdateTool;
end;
FormPaint(Self);
end;
procedure TIconForm.PencilDraw;
begin
with WorkingImage.Canvas do
begin
Pen.Color:= DrawingColor;
MoveTo(LastPos.X, LastPos.Y);
LineTo(EndPos.X, EndPos.Y);
Pixels[EndPos.X, EndPos.Y]:= DrawingColor;
end;
with IconImage.Canvas do
begin
Pen.Color:= DrawingColor;
MoveTo(LastPos.X, LastPos.Y);
LineTo(EndPos.X, EndPos.Y);
Pixels[EndPos.X, EndPos.Y]:= DrawingColor;
end;
Modified:= true;
ModifiedLabel.Visible:= true;
Drawn:= true;
end;
procedure TIconForm.FillDraw;
begin
with WorkingImage.Canvas do
begin
Brush.Color:= DrawingColor;
FloodFill(EndPos.X, EndPos.Y, WorkingColor, fsSurface);
end;
Modified:= true;
ModifiedLabel.Visible:= true;
NextUndo;
WorkingToUndo;
UndoToIcon;
FormPaint(Self);
end;
procedure TIconForm.LineDraw(ACanvas : TCanvas);
begin
with ACanvas do
begin
Pen.Color:= DrawingColor;
MoveTo(StartPos.X, StartPos.Y);
LineTo(EndPos.X, EndPos.Y);
Pixels[EndPos.X, EndPos.Y]:= DrawingColor;
end;
end;
procedure TIconForm.GetRectCorners(var SX, SY, EX, EY : integer);
begin
SX:= StartPos.X;
SY:= StartPos.Y;
EX:= EndPos.X;
EY:= EndPos.Y;
if SX > EX then
inc(SX)
else
if EX > SX then
inc(EX);
if SY > EY then
inc(SY)
else
if EY > SY then
inc(EY);
end;
procedure TIconForm.RectangleDraw(ACanvas : TCanvas);
var
SX, SY, EX, EY : integer;
begin
GetRectCorners(SX, SY, EX, EY);
with ACanvas do
begin
Pen.Color:= DrawingColor;
Rectangle(SX, SY, EX, EY);
end;
end;
procedure TIconForm.ClearRectangleDraw(ACanvas : TCanvas);
begin
ACanvas.Brush.Style:= bsClear;
RectangleDraw(ACanvas);
end;
procedure TIconForm.FilledRectangleDraw(ACanvas : TCanvas);
begin
ACanvas.Brush.Color:= DrawingColor;
RectangleDraw(ACanvas);
end;
procedure TIconForm.EllipseDraw(ACanvas : TCanvas);
var
SX, SY, EX, EY : integer;
begin
GetRectCorners(SX, SY, EX, EY);
with ACanvas do
begin
Pen.Color:= DrawingColor;
Ellipse(SX, SY, EX, EY);
end;
end;
procedure TIconForm.ClearEllipseDraw(ACanvas : TCanvas);
begin
ACanvas.Brush.Style:= bsClear;
EllipseDraw(ACanvas);
end;
procedure TIconForm.FilledEllipseDraw(ACanvas : TCanvas);
begin
ACanvas.Brush.Color:= DrawingColor;
EllipseDraw(ACanvas);
end;
end.